home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  18.5 KB  |  666 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <limits.h>
  9. #include <ctype.h>
  10. #include <errno.h>
  11. #ifndef NO_GETOPT_H
  12. #  include <getopt.h>
  13. #endif
  14. #include <signal.h>
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdio.h>
  19.  
  20. #include <h/envvar_str.h>
  21.  
  22. #define MAIN_C
  23. #define I_BUFFLOOP_C
  24. #define I_DISPLAY_C
  25. #define I_FOLDFILING_C
  26. #define I_GETMSG_C
  27. #define I_GETTK_C
  28. #define I_INIT_C
  29. #define I_KEYBOARD_C
  30. #define I_LOOP_C
  31. #define I_MESSAGES_C
  32. #define I_ORIEDT_C
  33. #define I_PROMPT_C
  34. #define I_SCREEN_C
  35. #define I_SHELL_C
  36. #define I_SIGNALS_C
  37. #define I_VIRTUAL_C
  38.  
  39. #include "origami.h"
  40. #include <lib/ori_add_lib.h>
  41. #include <lib/ori_rc_lib.h>
  42. /*}}}  */
  43.  
  44. /*{{{  variables*/
  45. public char kp_state='\0';
  46. public char const *rc_name=0;
  47. public unsigned char const *filearg;
  48. public TOKEN sig_macro[HISTORY_SIZE+1];
  49. public int sig_count=0;
  50. public boolean auto_save=False;
  51. public boolean interrupt_restore=False,
  52. #           if defined(SIGWINCH) || defined(MGR)
  53.                win_changed=False,
  54. #           endif
  55.             verbose=False,
  56.             aborted;
  57. public element null_element;
  58. public boolean no_suspend=False;
  59. public boolean no_pipe=False;
  60. /*}}}  */
  61.  
  62. /*{{{  language data*/
  63. #define LG_DAT(name,stxt,slg,etxt,elg) \
  64.  { { stxt,etxt },{ slg,elg },(unsigned char*)name }
  65. language_comment dialects[F_C_SIZE]=
  66.  { LG_DAT("None",(unsigned char*)empty_text,0,(unsigned char*)empty_text,0),
  67.    LANGDATA
  68.    LG_DAT("User",bd.m.dialect.lg_u_s,0,bd.m.dialect.lg_u_e,0),
  69.    LG_DAT("Inmos",(unsigned char*)"--",2,(unsigned char*)empty_text,0)
  70.  };
  71. /*}}}  */
  72.  
  73. /*{{{  main*/
  74. /*{{{  ori_arg_parse*/
  75. #define CMD_AL_LG (BIND_NAME_LEN+1)
  76. /*{{{  get_rcopt*/
  77. private char *get_rcopt(char *cmd,char *opts,char **val,boolean *set)
  78. {
  79.   int l;
  80.   char *o;
  81.  
  82.   /*{{{  get length of name, maybe handle argument*/
  83.   for (l=0;cmd[l];l++)
  84.      if (cmd[l]=='=')
  85.       { *set=True;
  86.         *val=cmd+l+1;
  87.         break;
  88.       }
  89.   /*}}}  */
  90.   for (o=opts;*o;)
  91.      if (!strncmp(o,cmd,l) && o[l]=='\0')
  92.       { o=o+l+1;
  93.         break;
  94.       }
  95.      else
  96.       { while (*++o);
  97.         while (*++o);
  98.         o++;
  99.       }
  100.  
  101.   return(o);
  102. }
  103. /*}}}  */
  104. /*{{{  get_arg_mark*/
  105. private boolean get_arg_mark(unsigned char*m,char **a)
  106. {
  107.   int i;
  108.  
  109.   for (i=FOLD_TAG_LENGTH;i;i--)
  110.      if (!(*m++=(char)*(*a)++))
  111.         return(True);
  112.   return (*(m-=FOLD_TAG_LENGTH)==' ' || *m=='\t');
  113. }
  114. /*}}}  */
  115.  
  116. private RETURNS ori_arg_parse
  117.  ( int argc,
  118.    char *argv[],
  119.    stackent * const ocl_args,
  120.    char **mark_mode
  121.  )
  122. {
  123.   char opts[NO_OCL_CMD_OPTS*2*CMD_AL_LG+2];
  124.   char *oriarg;
  125.   int env_oriargs;
  126.  
  127.   ori_name=get_prg_name(argv[0]);
  128.   env_oriargs=0;
  129.   if ((oriarg=getenv(ORIARG)))
  130.    /*{{{  divide ORIARG in single options*/
  131.    { for (;;oriarg++)
  132.       { switch (*oriarg)
  133.          { case ' ':
  134.            case '\t':
  135.               continue;
  136.            default:
  137.             { char *arg_buff;
  138.  
  139.               /* skipped leading spaces/tabs in ORIARG */
  140.               if ((arg_buff=paket_malloc(strlen(oriarg)+1)))
  141.                /*{{{  get new argc/argv, containing data from ORIARG*/
  142.                { int n;
  143.                  char **a;
  144.  
  145.                  strcpy(arg_buff,oriarg);
  146.                  /*{{{  get number of additional opts*/
  147.                  { char *s;
  148.  
  149.                    for (n=0,s=arg_buff;;)
  150.                     { switch (*s)
  151.                        { case ' ':
  152.                          case '\t':
  153.                             while (*++s==' ' || *s=='\t');
  154.                          case'\0':
  155.                             n++;
  156.                             if (*s)
  157.                                continue;
  158.                             break;
  159.                          default:
  160.                             s++;
  161.                             continue;
  162.                        }
  163.                       break;
  164.                     }
  165.                  }
  166.                  /*}}}  */
  167.                  if ((a=paket_malloc((argc+1+n)*sizeof(int*))))
  168.                   /*{{{  new argc/argv*/
  169.                   { char *s;
  170.  
  171.                     env_oriargs=n;
  172.                     a[0]=argv[0];
  173.                     memcpy(&(a[n+1]),&(argv[1]),argc*sizeof(char*));
  174.                     argv=a;
  175.                     argc+=n;
  176.                     for (s=arg_buff,a++;n;n--,a++)
  177.                      /*{{{  set pointer in argv, cut option at space/tab*/
  178.                      { *a=s;
  179.                        for (;;)
  180.                         { switch(*s)
  181.                            { default:
  182.                                 s++;
  183.                                 continue;
  184.                              case ' ':
  185.                              case '\t':
  186.                                 *s='\0';
  187.                                 while (*++s==' ' || *s=='\t');
  188.                              case '\0':
  189.                                 break;
  190.                            }
  191.                           break;
  192.                         }
  193.                      }
  194.                      /*}}}  */
  195.                   }
  196.                   /*}}}  */
  197.                  else
  198.                     goto arg_mem_full;
  199.                }
  200.                /*}}}  */
  201.               else
  202.                  goto arg_mem_full;
  203.             }
  204.            case '0':
  205.               /* ORIARG contains only space and tabs! */
  206.               break;
  207.          }
  208.         break;
  209.       }
  210.    }
  211.    /*}}}  */
  212.   /*{{{  options handling loop*/
  213.   {
  214.     /*{{{  variables*/
  215.     int c;
  216.     char const *nok;
  217.     boolean arg_init;
  218.     boolean rc_used;
  219.     /*}}}  */
  220.  
  221.     for
  222.      ( rc_used=arg_init=False,nok=0
  223.      ;   !nok
  224.       && (c=getopt(argc,argv,"a:d:ef:hik:l:m:nopt:vACDF:K:M:N:O:PR:S:T:VW:X:Z@:"))!=EOF
  225.      ; env_oriargs--
  226.      ) switch (c)
  227.         {
  228.           /*{{{  a delay,       alarmtime*/
  229.           case 'a':
  230.              alarm_time=atoi(optarg)*60;
  231.              if (alarm_time)
  232.               /*{{{  set auto-save and test time*/
  233.               { auto_save=True;
  234.                 if (alarm_time<MIN_ALARMTIME*60 || alarm_time>MAX_ALARMTIME*60)
  235.                    nok=(char*)get_msg
  236.                                ( MSG_ARG_FORMAT,
  237.                                  STR_F_ALARM,
  238.                                  MIN_ALARMTIME,
  239.                                  MAX_ALARMTIME
  240.                                );
  241.               }
  242.               /*}}}  */
  243.              else
  244.               /*{{{  don't use autosave*/
  245.               { auto_save=False;alarm_time=NORM_ALARMTIME*60; }
  246.               /*}}}  */
  247.              break;
  248.           /*}}}  */
  249.           /*{{{  d type,        displaytype*/
  250.           case 'd':
  251.              for (;;)
  252.               { int code;
  253.  
  254.                 switch ((code= *optarg++))
  255.                  { case 't':
  256.                       code= -atoi(optarg);
  257.                       chg_dsp_type((code>0)?0:code);
  258.                    case '\0':
  259.                       break;
  260.                    default:
  261.                       chg_dsp_type(code);
  262.                       continue;
  263.                  }
  264.                 break;
  265.               }
  266.              break;
  267.           /*}}}  */
  268.           /*{{{  e,             echo disabled*/
  269.           case 'e':
  270.              echo_disabled=True;
  271.              break;
  272.           /*}}}  */
  273.           /*{{{  f match,       match expression for diredit*/
  274.           case 'f':
  275.              add_history(match_history,(unsigned char*)optarg);
  276.              break;
  277.           /*}}}  */
  278.           /*{{{  h,             help*/
  279.           case 'h':
  280.              aborted=True;
  281.              break;
  282.           /*}}}  */
  283.           /*{{{  i,             inverse controls*/
  284.           case 'i':
  285.              chg_dsp_type('i');
  286.              break;
  287.           /*}}}  */
  288.           /*{{{  k basename,    rc-basename*/
  289.           case 'k':
  290.              if (arg_init)
  291.                 nok=STR_M_NORCCHANGE;
  292.              else
  293.                 rc_name=optarg;
  294.              break;
  295.           /*}}}  */
  296.           /*{{{  l line,        first line to display*/
  297.           case 'l':
  298.              if
  299.               (    startup_line
  300.                 || (startup_line=atoi(optarg))<=0
  301.               )
  302.                 nok=STR_M_LINE;
  303.              break;
  304.           /*}}}  */
  305.           /*{{{  m markname,    marktype*/
  306.           case 'm':
  307.              if (*mark_mode)
  308.                 nok=STR_M_MARK;
  309.              else
  310.                 *mark_mode=optarg;
  311.              break;
  312.           /*}}}  */
  313.           /*{{{  n,             no folding*/
  314.           case 'n':
  315.              init_buffer.e.fold_in=True;
  316.              break;
  317.           /*}}}  */
  318.           /*{{{  o,             overwrite*/
  319.           case 'o':
  320.              init_buffer.m.overwrite=True;
  321.              break;
  322.           /*}}}  */
  323.           /*{{{  p,             c-hash-mode*/
  324.           case 'p':
  325.              init_buffer.m.hash_shift=True;
  326.              break;
  327.           /*}}}  */
  328.           /*{{{  t size,        tab-mode*/
  329.           case 't':
  330.            { int code;
  331.  
  332.              code= -atoi(optarg);
  333.              chg_dsp_type((code>0)?0:code);
  334.              break;
  335.            }
  336.           /*}}}  */
  337.           /*{{{  v,             view-mode*/
  338.           case 'v':
  339.              init_buffer.m.read_only=init_buffer.m.user_view=True;
  340.              break;
  341.           /*}}}  */
  342.           /*{{{  A,             open argument list*/
  343.           case 'A':
  344.              arg_list=True;
  345.              break;
  346.           /*}}}  */
  347.           /*{{{  C,             copyright disabled*/
  348.           case 'C':
  349. #            ifdef SW_MSG
  350.                 copyright=False;
  351. #            endif
  352.              break;
  353.           /*}}}  */
  354.           /*{{{  D,             do_dump*/
  355.           case 'D':
  356.              do_dump=True;
  357.              break;
  358.           /*}}}  */
  359.           /*{{{  F nomatch,     nomatch expression for diredit*/
  360.           case 'F':
  361.              add_history(nomatch_history,(unsigned char*)optarg);
  362.              break;
  363.           /*}}}  */
  364.           /*{{{  K,             switch keypad*/
  365.           case 'K':
  366.              switch (kp_state= *optarg)
  367.               { default:
  368.                    nok=STR_M_KP;
  369.                 case 'A':
  370.                 case 'a':
  371.                 case 'N':
  372.                 case 'n':
  373.                    break;
  374.               }
  375.              break;
  376.           /*}}}  */
  377.           /*{{{  M marks,       give foldmarks directly*/
  378.           case 'M':
  379.              if
  380.               (    get_arg_mark(init_buffer.f.str.open_f,&optarg)
  381.                 || get_arg_mark(init_buffer.f.str.file_f,&optarg)
  382.                 || get_arg_mark(init_buffer.f.str.line_f,&optarg)
  383.                 || get_arg_mark(init_buffer.f.str.close_f,&optarg)
  384.                 || *optarg
  385.               )
  386.                 nok=M_FM;
  387.              break;
  388.           /*}}}  */
  389.           /*{{{  N buffsize,    tablesize*/
  390.           case 'N':
  391. #            ifdef VIRTUAL
  392.                 if ((vir_nodes=atoi(optarg))<0)
  393.                    nok=STR_M_VN;
  394. #            endif
  395.              break;
  396.           /*}}}  */
  397.           /*{{{  O value,       set OCL-var*/
  398.           case 'O':
  399.              arg_init=True;
  400.              if (*optarg)
  401.               /*{{{  handle sequence of initializations*/
  402.               { char *curr_opt;
  403.                 boolean set_rc_val;
  404.  
  405.                 for (set_rc_val=False,curr_opt=optarg;;optarg=curr_opt)
  406.                  {
  407.                    /*{{{  vars*/
  408.                    char *rc_val;
  409.                    int off;
  410.                    int v;
  411.                    char c;
  412.                    /*}}}  */
  413.  
  414.                    /*{{{  get command type, maybe expand alias*/
  415.                    c= *curr_opt;
  416.                    if (isalpha(c))
  417.                     /*{{{  decode alias*/
  418.                     { if
  419.                        (    (!rc_used && (rc_used=True,rcfileparser(opts,(char*)0)))
  420.                          || !(curr_opt=get_rcopt(curr_opt,opts,&rc_val,&set_rc_val))
  421.                        )
  422.                        { nok=M_INV_OCL;
  423.                          break;
  424.                        }
  425.                       else
  426.                          c=curr_opt[0];
  427.                     }
  428.                     /*}}}  */
  429.                    /*}}}  */
  430.                    /*{{{  get adress for setting*/
  431.                    off=0;
  432.                    if (c=='>')
  433.                     /*{{{  use another member of field*/
  434.                     { off=atoi(++curr_opt);
  435.                       if (off<0 || off>=DIM_OCL_CMD_OPTS)
  436.                        { nok=M_INV_OCL;
  437.                          break;
  438.                        }
  439.                       while ((c= *curr_opt),isdigit(c))
  440.                          curr_opt++;
  441.                     }
  442.                     /*}}}  */
  443.                    /*}}}  */
  444.                    if (c=='@')
  445.                     { curr_opt++;
  446.                       if (!set_rc_val)
  447.                          nok=M_INV_OCL;
  448.                       else
  449.                          add_history
  450.                           ( arg_history,
  451.                             *rc_val
  452.                              ? (unsigned char*)rc_val
  453.                              : (unsigned char*)one_space
  454.                           );
  455.                     }
  456.                    else
  457.                     /*{{{  numerical option*/
  458.                     {
  459.                       /*{{{  get value for op*/
  460.                       if (c=='-' || isdigit(c))
  461.                          c='=';
  462.                       else
  463.                          curr_opt++;
  464.                       if (*curr_opt=='?' && set_rc_val)
  465.                        { v=atoi(rc_val);
  466.                          curr_opt++;
  467.                        }
  468.                       else
  469.                        { v=atoi(curr_opt);
  470.                          while (isdigit(*curr_opt) || *curr_opt=='-')
  471.                             curr_opt++;
  472.                        }
  473.                       /*}}}  */
  474.                       /*{{{  handle op*/
  475.                       switch (c)
  476.                        { case '=': ocl_args[off].v =v;break;
  477.                          case '|': ocl_args[off].v|=v;break;
  478.                          case '&': ocl_args[off].v&=v;break;
  479.                          case '^': ocl_args[off].v^=v;break;
  480.                          case '+': ocl_args[off].v+=v;break;
  481.                          case '<':
  482.                             if (v>=0 && v<DIM_OCL_CMD_OPTS)
  483.                              { ocl_args[off].v=ocl_args[v].v;
  484.                                break;
  485.                              }
  486.                          default:  nok=M_INV_OCL;
  487.                        }
  488.                       /*}}}  */
  489.                     }
  490.                     /*}}}  */
  491.                    if (nok || *curr_opt=='\0')
  492.                       break;
  493.                  }
  494.               }
  495.               /*}}}  */
  496.              else
  497.               /*{{{  init 0 with 0*/
  498.                 ocl_args[0].v=0;
  499.               /*}}}  */
  500.              /*{{{  if error, prepare detailed error message*/
  501.              if (nok)
  502.                 nok=(char*)get_msg(MSG_ARG_FORMAT,nok,origami_name,optarg);
  503.              /*}}}  */
  504.              break;
  505.           /*}}}  */
  506.           /*{{{  P,             no open for /dev/tty*/
  507.           case 'P':
  508.              no_pipe=True;
  509.              break;
  510.           /*}}}  */
  511.           /*{{{  R rcpath,      resource file path*/
  512.           case 'R':
  513.              ori_path=optarg;
  514.              break;
  515.           /*}}}  */
  516.           /*{{{  S,             secure*/
  517.           case 'S':
  518.              secure=True;
  519.              shell_name=optarg;
  520.              break;
  521.           /*}}}  */
  522.           /*{{{  T title,       titlename*/
  523.           case 'T':
  524. #            ifdef WINDOW_TITLE_CHANGE
  525.                  w_title=optarg;
  526. #            endif
  527.              break;
  528.           /*}}}  */
  529.           /*{{{  V,             verbose*/
  530.           case 'V':
  531.              verbose=True;
  532.              break;
  533.           /*}}}  */
  534.           /*{{{  W,             statusline extension: window name*/
  535.           case 'W':
  536.              w_name=(unsigned char*)optarg;
  537.              break;
  538.           /*}}}  */
  539.           /*{{{  X,             extensions*/
  540.           case 'X':
  541. #            ifdef OWN_ARG_HANDLE
  542.                 OWN_ARG_HANDLE
  543. #            endif
  544.              break;
  545.           /*}}}  */
  546.           /*{{{  Z,             no suspend*/
  547.           case 'Z':
  548.               no_suspend=True;
  549.               break;
  550.           /*}}}  */
  551.           /*{{{  @,             debug arguments*/
  552.           case '@':
  553.              arg_debug(optarg);
  554.              break;
  555.           /*}}}  */
  556.           /*{{{  else, error*/
  557.           case '?':
  558.           default:
  559.              nok=(char*)empty_text;
  560.              break;
  561.           /*}}}  */
  562.        }
  563.     /*{{{  errorcases in args*/
  564.     if (nok || aborted)
  565.      { if (nok)
  566.         { if (*nok)
  567.            { if (env_oriargs>=0)
  568.                 eputs("origami ("ORIARG"):");
  569.              else
  570.                 eputs("origami: ");
  571.              eputs(nok);
  572.              eputc('\n');
  573.            }
  574.           eputs(get_short_usage());
  575.         }
  576.        else
  577.           eputs(get_long_usage());
  578.        return(nok?r_arg_err:r_ok);
  579.      }
  580.     /*}}}  */
  581.     if (!arg_init)
  582.         ocl_args[0].v= -1;
  583.   }
  584.   /*}}}  */
  585.   /*{{{  inputfiles*/
  586.   { int c;
  587.  
  588.     if ((argc-optind)<=1)
  589.        arg_list=False;
  590.     for (c=optind,filearg=0;c!=argc;c++)
  591.      /*{{{  expand ~ and set to filelist*/
  592.      { unsigned char *f;
  593.  
  594.        f=(unsigned char*)(argv[c]);
  595.        /*{{{  add to file-history*/
  596.        add_history(file_history,f);
  597.        /*}}}  */
  598.        /*{{{  expand ~*/
  599.        ustrcpy(print_buffer,f);
  600.        home_expand((char*)print_buffer);
  601.        /*}}}  */
  602.        /*{{{  maybe copy to malloced space*/
  603.        if (ustrcmp(print_buffer,f))
  604.           if ((f=paket_malloc(ustrlen(print_buffer)+1)))
  605.              ustrcpy(f,print_buffer);
  606.           else
  607.              goto arg_mem_full;
  608.        else
  609.           f=(unsigned char*)(argv[c]);
  610.        /*}}}  */
  611.        add_edit_file((char*)f,1,False);
  612.        if (!filearg) filearg=f;
  613.      }
  614.      /*}}}  */
  615.   }
  616.   /*}}}  */
  617.   /*{{{  maybe free malloced data from ORIARG handling*/
  618.   if (oriarg)
  619.      paket_free(argv);
  620.   /*}}}  */
  621.  
  622.   return(exit_failure);
  623.  
  624. arg_mem_full:
  625.   oputs((unsigned char*)M_NO_MEMORY);
  626.   oputc('\n');
  627.   return(r_mem_full);
  628. }
  629. /*}}}  */
  630.  
  631. int main(int argc, char *argv[])
  632. {
  633.   RETURNS new_exit;
  634.  
  635.   os_init();
  636.   /*{{{  read arguments and rc, init the editor*/
  637.   { stackent ocl_args[DIM_OCL_CMD_OPTS];
  638.     int i;
  639.     char *mark_mode=0;
  640.  
  641.     for (i=DIM_OCL_CMD_OPTS;i--;ocl_args[i].v=0);
  642.     if ((new_exit=ori_arg_parse(argc,argv,ocl_args,&mark_mode))!=exit_failure)
  643.        return(new_exit);
  644.     start_debug();
  645.     os_init_args_read();
  646.     /*{{{  init the editor*/
  647.     HostBegin(mark_mode);
  648. #    ifdef VIRTUAL
  649.        if (init_data_handle())
  650.           exit_origami(r_vir_err,get_msg(F_VM_FAIL,"access",strerror(errno)));
  651. #    endif
  652.     initialise();
  653.     /*}}}  */
  654.     os_init_rc_read();
  655.     memcpy(&(ocl_var[var_ocl_arg]),ocl_args,DIM_OCL_CMD_OPTS*sizeof(stackent));
  656.   }
  657.   /*}}}  */
  658.   new_exit=main_editor_loop();
  659.   /*{{{  try to do a pretty exit*/
  660.   msg_message(M_BYE);
  661.   exit_origami(new_exit,print_buffer[0]?print_buffer:(unsigned char*)0);
  662.   /*}}}  */
  663.   return exit_failure;
  664. }
  665. /*}}}  */
  666.